公司主页 文档归类 淘宝

BLE一次能传多少数据

BLE到底一包能够收发多少数据。这是我们很多开发者都会关心的,正如我们知道BLE5.0物理层设计2Mpbs的码元率,实际我们的数据传输速率远远到不了这个级别,主要原因就是我们没有办法直接单次发送1M或者1K数据,必须按照我们知道的ATT_MTU作为最大值进行拆包发送,不断拆包的过程中导致整体蓝牙有效数据吞吐量下降。本章节,我们实用性触发研究如何究竟蓝牙一包能够发送多少数据。

以下是GAPP Client 进行特征值写请求的完整抓包,AttValue表示写入的值,该值的最大长度到底是多少呢,本文将详细研究并且验证。

本文的正确打开姿势,我们希望你已经仔细阅读并理解协议栈的L2CAP,和BLE4.2/5.0全新支持的 LE 数据扩展功能:

术语

术语 解释
PDU Potocal Data Unit 协议数据单元,对于协议栈数据单元我们应该理解为蓝牙协议分层的消息实体的完整封装,例如LL PDU表示我们 逻辑链路层的协议消息的完整封装
MTU Maximum Transmission Unit 最大传输单元,和本文研究的BLE数据包的最大长度意思接近
LL Logic Link 逻辑链路层
PHY physical layer 物理层 蓝牙协议的最底层

分析

在 BLE PHY 包格式由以下组成,排除 前导码、访问地址、CRC地址 对于BLE4.0/BLE4.1 上层协议(LL)最大可以包含39字节长度的PDU(协议数据单元)。

但是更新后的BLE4.2/BLE5.0 直接升级硬件,将这一长度扩展到257。但是默认了兼容BLE4.0/4.1还是采用了上面的39设计。

注意:PHY 的数据包最大长度直接由硬件决定,也是限制我们BLE 数据包大小的根本原因。换句话说,PHY的硬件寄存器/存储器/FIFO 等直接决定了我们蓝牙数据包最大长度。

对于蓝牙协议分层设计来看,逻辑链路层是最底层,已经正常连接的两个设备之间通信PDU主要由LL Data PDU组成。这里的LL Playload作为我们上层协议的负载。

逻辑链路层再往上就是L2CAP——逻辑逻辑链路控制适配协议,如下的Basic L2CAP Header+Information Payload组成我们这里的基本帧(B-frame)。

L2CAP协议再上就是我们操作特征值的ATT层,这一层数据长度被 最大传输单元 ATT_MTU限制,ATT_Payload由Attribute OPCode+Attribute Parames+Authentication Signature(可选)组成。排除12字节可选的认证签名,和一个字节属性操作码。

对于我们这里的写属性值,其Attribute Parameters=其Attribute Handle(2) + Attribute Value,Attribute Value就是我们操作属性的值,其最大长度=ATT_MTU-Attribute OPCode(1)-Attribute Handle(2)=ATT_MTU-3。

同样地,对于读操作属性,主要包含在ReadResponse 操作码。最大长度=ATT_MTU-Attribute OPCode(1)=ATT_MTU-1。

再总结下,读写属性值最大有效数据长度直接由ATT_MTU决定,但是根本收LL PDU 大小限制

更改simpler_peripheral 配置更大MTU


对于simpler_peripheral工程我们的开发板作为GATT Server决定 ATT_MTU的最大值。通过以下宏配置。

simpler_peripheral默认的ATT_MTU为23,也就是我们实际写属性值最大长度为20。GATT 服务端ATT_MTU由以上宏定义,GATT客户端可以通过GATT_ExchangeMTU()命令配置。GATT服务端根据当前的配置的ATT_MTU决定是否生效。例如我们这里的simple_peripheral作为GATT服务端,以更改宏L2CAP_MTU_SIZE为150,GATT_ExchangeMTU()需要配置到200,我们将返回150,表示生效。

注意: 对于GATT_ExchangeMTU()操作,我们只能由GATT Client发起,并且GATT服务端返回实际支持最大ATT_MTU。

参考《运行第一个例程》,我们直接更改最大ATT_MTU到251,并且通过《 BTool》配置客户端ATT_MTU到251,并且更改simple_peripheral characteristic 5数组为251。属性为可读可写。

更改工程

//source\ti\ble5stack\icall\inc\ble_user_config.h  MAX_PDU_SIZE Line 214
// Maximum size in bytes of the BLE HCI PDU. Valid range: 27 to 255
// The maximum ATT_MTU is MAX_PDU_SIZE - 4.
#ifndef MAX_PDU_SIZE
#if defined(BLE_V42_FEATURES) && (BLE_V42_FEATURES & SECURE_CONNS_CFG)
  #define MAX_PDU_SIZE                  255
#else
  #define MAX_PDU_SIZE                  27
#endif //(BLE_V42_FEATURES & SECURE_CONNS_CFG)
#endif

我们配置L2CAP MAX_PDU_SIZE 为255, ATT_MTU 最大 为251 读写特征值最大长度应该ATT_MTU-3=248;

//source\ti\blestack\profiles\simple_profile\simple_gatt_profile.h SIMPLEPROFILE_CHAR5_LEN Line 85
#define SIMPLEPROFILE_CHAR5_LEN             248

因为我们增加了特征值5的大小为240,对于参考特征的栈空间也得增加,对应着我们的任务栈,否则程序可能会跑飞。

//examples\rtos\CC2640R2_LAUNCHXL\blestack\simple_peripheral\src\app\simple_peripheral.c SBP_TASK_STACK_SIZE Line 180
#ifndef SBP_TASK_STACK_SIZE
#define SBP_TASK_STACK_SIZE                   1024
#endif

注意:这里之所以要加大任务栈否则任务要跑飞,是因为部分任务直接分配了栈空间进行特征值拷贝。

同时为了更好测试,我们直接将特诊5的属性更改为直接读写,不需要配对连接。

//source\ti\blestack\profiles\simple_profile\cc26xx\simple_gatt_profile.c Characteristic Value 5 Line 323
    // Characteristic Value 5
    {
        { ATT_BT_UUID_SIZE, simpleProfilechar5UUID },
        GATT_PERMIT_READ|GATT_PERMIT_WRITE,
        0,
        simpleProfileChar5
    },

但是simple_peripheral默认没有进行Characteristic Value 5 写操作,所以我们需要更改。

//source\ti\blestack\profiles\simple_profile\cc26xx\simple_gatt_profile.c  simpleProfile_WriteAttrCB Line660
    case SIMPLEPROFILE_CHAR5_UUID:
       if(len+offset>SIMPLEPROFILE_CHAR5_LEN) {
        status = ATT_ERR_INVALID_VALUE_SIZE;
       }
    
       //Write the value
       if ( status == SUCCESS ) {
           uint8 *pCurVal = (uint8 *)pAttr->pValue;
           for(uint8 i=0;i<len;i++) {
                *(pCurVal+offset+i)=*(pValue+i);
           }
           if(pAttr->pValue == simpleProfileChar5) {
               notifyApp = SIMPLEPROFILE_CHAR5;
           }
       }
       break;

同时我们要在应用程序回调处理Characteristic Value 5的写入操作,方便打印到串口调试。

//examples\rtos\CC2640R2_LAUNCHXL\blestack\simple_peripheral\src\app\simple_peripheral.c SimpleBLEPeripheral_processCharValueChangeEvt Line 1183
    case SIMPLEPROFILE_CHAR5:
        SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR5, newValue);
        
        sprintf(sprintChar,"%s","Char 5: ");
        //!< 大概没60个字符要换一行
        line=7;
        index=8;
        for(uint8_t i=0;i<SIMPLEPROFILE_CHAR5_LEN;i++) {
            sprintf(sprintChar+index,  "%02X", *(newValue+i));
            index=index+2;
            //!< 每60个字符进行换行打印。
            if(index%60==0) {
                index=0;
                Display_print1(dispHandle,line++ ,0,"%s",sprintChar);
            }
        }
        if(index>0) {  
            Display_print1(dispHandle,line,0,"%s",sprintChar);
        }
        break;

现象


总结

尽管我们通过GATT 服务端配置更大MTU,通过GATT Client 交换,成功读取200字节的特征值,但是在我们抓包分析不难发现在Controller,的链路层还是被拆分为最大长度27字节发送。通过前面分析我们已经不难理解,BLE4.2/5.0为了兼容 BLE4.0/4.1设备,所以默认TX PDU 设计成了27字节。尽管我们再Host配置更了更大的ATT_MTU,其实只是L2CAP帮我们进行了拆分和重组。为了获取到更大数据吞吐量,我们继续研究 BLE4.2/5.0新增功能 LE Data Extence。

Troubleshooting

因为我们更改的GATT 服务端也就是simple_peripheral 工程的默认MTU 大小,所以正常读写特征值前我们需要进行ATT_Exchange_MTU_Req 请求。否则会直接失败。

LE Data Extension

LE Data Length Extension 文章我们详细讲解过,BLE4.2/5.0 已经硬件支持257的LL Data Payload Size。但是为了兼容BLE4.1/4.0所以默认保留该功能, 现在我们详细讲解如何使能该功能,实现真正意义的最大ATT_MTU发送,同时体验BLE4.2/5.0全新速率。

对于BLE4.2/5.0设备,默认支持TX_PDU大小为了兼容BLE4.1/4.0 设备,默认设置为27字节/328us,同时又为了又为了兼容BLE4.2/5.0RX PDU默认设置为251字节/2152us。对于默认使能 251/2120us。只需要主从收发的任意一方设置自己的TX_PDU为251字节/2120us,那么收发双发就会直接发起协商功能。

所以这里我们直接设置Peripheral/Salve TX_PDU为251字节/2120us。在我们simple_peripheral工程 SimpleBLEPeripheral_init加入以下代码

    #define APP_SUGGESTED_PDU_SIZE 251
    #define APP_SUGGESTED_TX_TIME 2120

    //This API is documented in hci.h
    HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE ,APP_SUGGESTED_TX_TIME);

抓包分析

+----------------------------------------------------+----------------- - - -
|     Packet sniffer frame header                    |
+----+-------------+-------------------------+-------+
|info| Packet nbr. | Time stamp              | Length|  Packet data
+----+-------------+-------------------------+-------+----------------- - - -
| 01 | E1 00 00 00 | 29 0C 05 0E 02 00 00 00 | 15 00 | 14 BD AA 6D C4  0F 09  **14** ** FB 00 48 08 1B 00 48 01 ** 75 9A 9B 2A 9A
+----+-------------+-------------------------+-------+----------------- - - -
+----------------------------------------------------+----------------- - - -
|     Packet sniffer frame header                    |
+----+-------------+-------------------------+-------+
|info| Packet nbr. | Time stamp              | Length|  Packet data
+----+-------------+-------------------------+-------+----------------- - - -
| 01 | E2 00 00 00 | C2 0A 07 0E 02 00 00 00 | 15 00 | 14 BD AA 6D C4  0B 09  **14** ** FB 00 48 08 1B 00 48 01**   B3 1B C9 2E 9A
+----+-------------+-------------------------+-------+----------------- - - -
+----------------------------------------------------+----------------- - - -
|     Packet sniffer frame header                    |
+----+-------------+-------------------------+-------+
|info| Packet nbr. | Time stamp              | Length|  Packet data
+----+-------------+-------------------------+-------+----------------- - - -
| 01 | E3 00 00 00 | 3C 0B 85 10 02 00 00 00 | 15 00 | 14 BD AA 6D C4  03 09  **15**  **FB 00 48 08 1B 00 48 01**  C7 83 7F 26 82
+----+-------------+-------------------------+-------+----------------- - - -

+----------------------------------------------------+----------------- - - -
|     Packet sniffer frame header                    |
+----+-------------+-------------------------+-------+
|info| Packet nbr. | Time stamp              | Length|  Packet data
+----+-------------+-------------------------+-------+----------------- - - -
| 01 | E4 00 00 00 | D7 09 87 10 02 00 00 00 | 15 00 | 14 BD AA 6D C4 07 09  **15**  **FB 00 48 08 1B 00 48 01**  01 02 2D 34 82
+----+-------------+-------------------------+-------+----------------- - - -

加入我们

文章所有代码、工具、文档开源。加入我们QQ群 591679055获取更多支持,共同研究CC2640R2F&BLE5.0。

CC2640R2F&BLE5.0-乐控畅联 © Copyright 2017, 成都乐控畅联科技有限公司.